#include "../pch.h"
#include "REFXMLName.h"

namespace BFX
{

REFXMLAttribute::REFXMLAttribute(REFXMLName* pName, REFXMLDocument* pDoc) :
	REFXMLNode(pDoc)
{
	BFX_ASSERT(pName != NULL);
	BFX_ASSERT(pDoc != NULL);

	m_pName = pName;
	m_pLastChild = NULL;
	m_pParentNode = NULL;
}
REFXMLAttribute::REFXMLAttribute(const UniString& strPrefix, const UniString& strLocalName, const UniString& strNamespaceURI, REFXMLDocument* pDoc)
	: REFXMLNode(pDoc)
{
	m_pName = pDoc->AddAttrXmlName(strPrefix, strLocalName, strNamespaceURI);
	m_pLastChild = NULL;
	m_pParentNode = NULL;
}

REFXMLAttribute::~REFXMLAttribute()
{
}

REFXMLElement* REFXMLAttribute::GetOwnerElement() const
{
	return (REFXMLElement*)m_pParentNode;
}

UniString REFXMLAttribute::GetName() const
{
	return m_pName->GetName();
}

UniString REFXMLAttribute::GetLocalName() const
{
	return m_pName->GetLocalName();
}

UniString REFXMLAttribute::GetNamespaceURI() const
{
	return m_pName->GetNamespaceURI();
}

UniString REFXMLAttribute::GetPrefix() const
{
	return m_pName->GetPrefix();
}

void REFXMLAttribute::SetPrefix(const UniString& strPrefix)
{
	m_pName = m_pName->GetOwnerDocument()->AddAttrXmlName(strPrefix, GetLocalName(), GetNamespaceURI()/*, SchemaInfo */);
}

XMLNodeType REFXMLAttribute::GetNodeType() const
{
	return XMLNodeType_Attribute;
}

REFXMLDocument* REFXMLAttribute::GetOwnerDocument() const
{
	return m_pName->GetOwnerDocument();
}

UniString REFXMLAttribute::GetValue() const
{
	return GetInnerText();
}
void REFXMLAttribute::SetValue(const UniString& strValue)
{
	SetInnerText(strValue);
}

void REFXMLAttribute::SetInnerText(const UniString& strText)
{
	if (PrepareOwnerElementInElementIdAttrMap())
	{
		UniString strOldText = REFXMLNode::GetInnerText();
		REFXMLNode::SetInnerText(strText);
		ResetOwnerElementInElementIdAttrMap(strOldText);
	}
	else
	{
		REFXMLNode::SetInnerText(strText);
	}
}

bool REFXMLAttribute::PrepareOwnerElementInElementIdAttrMap()
{
	REFXMLDocument* pOwnerDocument = GetOwnerDocument();
	if (pOwnerDocument->GetDtdSchemaInfo() != NULL)	 // DTD exists
	{
		REFXMLElement* pOwnerElement = GetOwnerElement();
		if (pOwnerElement != NULL)
			return pOwnerElement->GetAttributes()->PrepareParentInElementIdAttrMap(GetPrefix(), GetLocalName());
	}
	return false;
}

void REFXMLAttribute::ResetOwnerElementInElementIdAttrMap(const UniString& strOldInnerText)
{
	REFXMLElement* pOwnerElement = GetOwnerElement();
	if (pOwnerElement != NULL)
		pOwnerElement->GetAttributes()->ResetParentInElementIdAttrMap(strOldInnerText, GetInnerText());
}

void REFXMLAttribute::SetInnerXml(const UniString& str)
{
	RemoveAll();
	// TODO: Load xml
	BFX_ASSERT(0);
}

// Gets the parent of this node (for nodes that can have parents).
REFXMLNode* REFXMLAttribute::GetParentNode() const
{
	return NULL;
}

// Saves the current node to the specified XmlWriter.
void REFXMLAttribute::WriteTo(REFXMLWriter* w) const
{
	w->WriteStartAttribute(GetPrefix(), GetLocalName(), GetNamespaceURI());
	WriteContentTo(w);
	w->WriteEndAttribute();
}

// Saves all the children of the node to the specified XmlWriter.
void REFXMLAttribute::WriteContentTo(REFXMLWriter* w) const
{
	for (REFXMLNode* pNode = GetFirstChild(); pNode != NULL; pNode = pNode->GetNextSibling())
	{
		pNode->WriteTo(w);
	}
}

void REFXMLAttribute::SetParent(REFXMLNode* pNode)
{
	m_pParentNode = pNode;
}

bool REFXMLAttribute::IsContainer() const
{
	return true;
}

REFXMLLinkedNode* REFXMLAttribute::GetFirstNode() const
{
	return m_pFirstChild;
}

void REFXMLAttribute::SetFirstNode(REFXMLLinkedNode* pNode)
{
	m_pFirstChild = pNode;
}

REFXMLLinkedNode* REFXMLAttribute::GetLastNode() const
{
	return m_pLastChild;
}

void REFXMLAttribute::SetLastNode(REFXMLLinkedNode* pNode)
{
	m_pLastChild = pNode;
}

bool REFXMLAttribute::IsValidChildType(XMLNodeType type) const
{
	return (type == XMLNodeType_Text) || (type == XMLNodeType_EntityReference);
}

REFXMLName* REFXMLAttribute::GetXmlName() const
{
	return m_pName;
}

void REFXMLAttribute::SetXmlName(REFXMLName* pName)
{
	m_pName = pName;
}

//////////////////////////////////////////////////////////////////////////////

REFXMLUnspecifiedAttribute::REFXMLUnspecifiedAttribute(const UniString& strPrefix, const UniString& strLocalName, const UniString& strNamespaceURI, REFXMLDocument* pDoc)
	: REFXMLAttribute(strPrefix, strLocalName, strNamespaceURI, pDoc)
{
	m_bSpecified = false;
}

REFXMLUnspecifiedAttribute::~REFXMLUnspecifiedAttribute()
{
}

// Sets the concatenated values of the node and all its children.
void REFXMLUnspecifiedAttribute::SetInnerText(const UniString& str)
{
	REFXMLAttribute::SetInnerText(str);
	m_bSpecified = true;
}

// Inserts the specified node immediately before the specified reference node.
REFXMLNode* REFXMLUnspecifiedAttribute::InsertBefore(REFXMLNode* pNewChild, const REFXMLNode* pRefChild)
{
	REFXMLNode* pNode = REFXMLAttribute::InsertBefore(pNewChild, pRefChild);
	m_bSpecified = true;
	return pNode;
}
// Inserts the specified node immediately after the specified reference node.
REFXMLNode* REFXMLUnspecifiedAttribute::InsertAfter(REFXMLNode* pNewChild, const REFXMLNode* pRefChild)
{
	REFXMLNode* pNode = REFXMLAttribute::InsertAfter(pNewChild, pRefChild);
	m_bSpecified = true;
	return pNode;
}

// Replaces the child node oldChild with newChild node.
REFXMLNode* REFXMLUnspecifiedAttribute::ReplaceChild(REFXMLNode* pNewChild, REFXMLNode* pOldChild)
{
	REFXMLNode* pNode = REFXMLAttribute::ReplaceChild(pNewChild, pOldChild);
	m_bSpecified = true;
	return pNode;
}
// Removes specified child node.
REFXMLNode* REFXMLUnspecifiedAttribute::RemoveChild(REFXMLNode* pOldChild)
{
	REFXMLNode* pNode = REFXMLAttribute::RemoveChild(pOldChild);
	m_bSpecified = true;
	return pNode;
}
// Adds the specified node to the end of the list of children of this node.
REFXMLNode* REFXMLUnspecifiedAttribute::AppendChild(REFXMLNode* pNewChild)
{
	REFXMLNode* pNode = REFXMLAttribute::AppendChild(pNewChild);
	m_bSpecified = true;
	return pNode;
}

// Saves the current node to the specified XmlWriter.
void REFXMLUnspecifiedAttribute::WriteTo(REFXMLWriter* w) const
{
	if (m_bSpecified)
		REFXMLAttribute::WriteTo(w);
}

bool REFXMLUnspecifiedAttribute::IsSpecified() const
{
	return m_bSpecified;
}

void REFXMLUnspecifiedAttribute::SetSpecified(bool bSpecified)
{
	m_bSpecified = bSpecified;
}

}	//	namespace BFX
